﻿using System;
using System.Web.Mvc;
using System.Web.Security;
using Xenta.Attributes;
using Xenta.Utils;

namespace Xenta.Web.Controllers
{
    public sealed class AccessController : ExtController
    {
        #region GET/POST Actions

        [HttpGet, RestoreState]
        public ActionResult SignIn()
        {
            return View();
        }

        [HttpPost, PersistState]
        public ActionResult SignIn(string email, string password)
        {
            email = StringHelper.EnsureNotNull(email).TrimToLen(100);
            password = StringHelper.EnsureNotNull(password).TrimToLen(100);

            try
            {
                var m = Svc.ProcessOperation("OpenSession", new
                {
                    Identity = email,
                    Password = password,
                    Source = HttpContext.Request.GetUserHostAddress()
                }, new
                {
                    DisclosureLevel = "Keys"
                });
                FormsAuthentication.SetAuthCookie(JDM.String(m.Guid), true);
            }
            catch(Exception ex)
            {
                ModelState.AddModelError("API", ex);
            }
            if(ModelState.IsValid)
                return RedirectToAction(Loc.Act("Init").Ctrl("Account").Localized());

            return RedirectToAction(Loc.Act("SignIn").Set(new
            {
                email
            }).Localized());
        }

        [HttpGet, RestoreState]
        public ActionResult SignUp()
        {
            if(Svc.Config<Boolean>(Par.In("Core").Of("CreateAccount").Name("Restricted")))
                return RedirectToAction(Loc.Act("SignIn").Localized());
            return View();
        }

        [HttpPost, PersistState]
        public ActionResult SignUp(string email,
            string username,
            string password,
            string captcha)
        {
            if(Svc.Config<Boolean>(Par.In("Core").Of("CreateAccount").Name("Restricted")))
                return RedirectToAction(Loc.Act("SignIn").Localized());

            string expectedCaptcha = TempData.RestoreObject<String>("SignUp");
            if(!String.IsNullOrEmpty(expectedCaptcha) &&
                !String.IsNullOrEmpty(captcha) &&
                expectedCaptcha.Equals(captcha))
            {
                email = StringHelper.EnsureNotNull(email).TrimToLen(100);
                password = StringHelper.EnsureNotNull(password).TrimToLen(100);

                try
                {
                    Svc.ProcessOperation("CreateAccount", new
                    {
                        LocalizationProfileID = JDM.Int32(Svc.Localization.EntityID),
                        Email = email,
                        Username = username,
                        Password = password
                    });
                }
                catch(Exception ex)
                {
                    ModelState.AddModelError("API", ex);
                }
                if(ModelState.IsValid)
                {
                    if(Svc.Config<Boolean>(Par.In("Core").Of("AccountEntity").Name("VerificationRequired")))
                    {
                        return RedirectToAction(Loc.Act("Verify").Set(new
                        {
                            email
                        }).Localized());
                    }
                    else
                    {
                        return RedirectToAction(Loc.Act("SignIn").Set(new
                        {
                            email
                        }).Localized());
                    }
                }
            }
            else
                ModelState.AddModelError("WebPortal", Err.Of(this).NotValid("Captcha"));

            return RedirectToAction(Loc.Act("SignUp").Localized());
        }

        [HttpGet]
        public ActionResult SignOut()
        {
            if(Svc.IsAuthenticated)
            {
                Svc.ProcessOperation("CloseSession", new
                {
                    EntityID = JDM.Int32(Svc.Session.EntityID)
                });
                FormsAuthentication.SignOut();
            }
            return RedirectToAction(Loc.Act("SignIn").Localized());
        }

        [HttpGet, RestoreState]
        public ActionResult Recover()
        {
            return View();
        }

        [HttpPost, PersistState]
        public ActionResult Recover(string email, string captcha)
        {
            string expectedCaptcha = TempData.RestoreObject<String>("Recover");
            if(!String.IsNullOrEmpty(expectedCaptcha) &&
                !String.IsNullOrEmpty(captcha) &&
                expectedCaptcha.Equals(captcha))
            {
                email = StringHelper.EnsureNotNull(email).TrimToLen(100);

                try
                {
                    Svc.ProcessOperation("ChangeAccountPasswordByEmail", new
                    {
                        Email = email,
                        Password = StringHelper.Random(8)
                    });
                }
                catch(Exception ex)
                {
                    ModelState.AddModelError("API", ex);
                }

                if(ModelState.IsValid)
                {
                    return RedirectToAction(Loc.Act("SignIn").Set(new
                    {
                        email
                    }).Localized());
                }
            }
            else
                ModelState.AddModelError("WebPortal", Err.Of(this).NotValid("Captcha"));

            return RedirectToAction(Loc.Act("Recover").Set(new
            {
                email
            }).Localized());
        }

        [HttpGet, RestoreState]
        public ActionResult Verify()
        {
            if(!Svc.Config<Boolean>(Par.In("Core").Of("AccountEntity").Name("VerificationRequired")))
                return RedirectToAction(Loc.Act("SignIn").Localized());
            return View();
        }

        [HttpPost, PersistState]
        public ActionResult Verify(string email, string code, string captcha)
        {
            if(!Svc.Config<Boolean>(Par.In("Core").Of("AccountEntity").Name("VerificationRequired")))
                return RedirectToAction(Loc.Act("SignIn").Localized());

            string expectedCaptcha = TempData.RestoreObject<String>("Verify");
            if(!String.IsNullOrEmpty(expectedCaptcha) &&
                !String.IsNullOrEmpty(captcha) &&
                expectedCaptcha.Equals(captcha))
            {
                var m = Svc.ProcessOperation("GetAccountByEmail", new
                {
                    Email = email
                });
                if(m != null)
                {
                    try
                    {
                        m = Svc.ProcessOperation("CommitAccountVerification", new
                        {
                            EntityID = JDM.Int32(m.EntityID),
                            VerificationCode = code
                        }, new
                        {
                            DisclosureLevel = "Base" 
                        });
                        if(JDM.HasFlags(m.Flags, "Verified"))
                        {
                            return RedirectToAction(Loc.Act("SignIn").Set(new
                            {
                                email
                            }).Localized());
                        }
                    }
                    catch(Exception ex)
                    {
                        ModelState.AddModelError("API", ex);
                    }
                }
            }
            else
                ModelState.AddModelError("WebPortal", Err.Of(this).NotValid("Captcha"));

            return RedirectToAction(Loc.Act("Verify").Set(new
            {
                email,
                code
            }).Localized());
        }

        [HttpGet]
        public ActionResult Captcha(string key)
        {
            string txt = StringHelper.Random(4);
            var img = ImageHelper.Captcha(txt, 180, 50);

            TempData.PersistObject(key, txt);

            return File(img, "image/gif");
        }

        #endregion

        #region AJAX Actions

        [HttpPost]
        public ActionResult CheckEmail(string email)
        {
            var res = Svc.ProcessOperation("CheckAccountByEmail", new
            {
                Email = email
            });
            return Json(!JDM.Boolean(res));
        }

        [HttpPost]
        public ActionResult CheckUsername(string username)
        {
            var res = Svc.ProcessOperation("CheckAccountByUsername", new
            {
                Username = username
            });
            return Json(!JDM.Boolean(res));
        }

        #endregion
    }
}
